const router = require("koa-router")();
const crypto = require("crypto");
const { query } = require("../utils/db");
const TokenManager = require("../utils/token");

/**
 * 生成随机token
 * @returns {string} 返回32位的随机字符串
 */
function generateToken() {
  return crypto.randomBytes(16).toString("hex");
}

/**
 * @swagger
 * /login:
 *   post:
 *     summary: 用户登录
 *     description: 用户登录接口，返回token
 *     tags: [用户认证]
 *     requestBody:
 *       required: true
 *       content:
 *         application/json:
 *           schema:
 *             type: object
 *             required:
 *               - username
 *               - password
 *             properties:
 *               username:
 *                 type: string
 *                 description: 用户名
 *               password:
 *                 type: string
 *                 description: 密码
 *     responses:
 *       200:
 *         description: 登录成功
 *         content:
 *           application/json:
 *             schema:
 *               type: object
 *               properties:
 *                 code:
 *                   type: number
 *                   example: 200
 *                 message:
 *                   type: string
 *                   example: 登录成功
 *                 data:
 *                   type: object
 *                   properties:
 *                     username:
 *                       type: string
 *                       example: admin
 *                     token:
 *                       type: string
 *                       example: f7d0c1e2b3a4...
 *       401:
 *         description: 用户名或密码错误
 *       500:
 *         description: 服务器错误
 */
router.post("/login", async (ctx, next) => {
  try {
    // 从请求体中获取用户名和密码
    const { username, password } = ctx.request.body;

    // 参数验证
    if (!username || !password) {
      ctx.status = 400;
      ctx.body = {
        code: 400,
        message: "用户名和密码不能为空",
      };
      return;
    }

    // 从数据库查询用户
    const sql = "SELECT * FROM userinfo WHERE username = ? AND password = ?";
    const users = await query(sql, [username, password]);

    if (users && users.length > 0) {
      const user = users[0];
      // 生成随机token
      const token = generateToken();

      // 保存token到数据库
      const saved = await TokenManager.saveToken(user.id, token);
      if (!saved) {
        throw new Error("保存token失败");
      }

      ctx.body = {
        code: 200,
        message: "登录成功",
        data: {
          username: username,
          token: token,
        },
      };
    } else {
      ctx.status = 401;
      ctx.body = {
        code: 401,
        message: "用户名或密码错误",
      };
    }
  } catch (error) {
    console.error("登录错误:", error);
    ctx.status = 500;
    ctx.body = {
      code: 500,
      message: "服务器内部错误",
    };
  }
});

/**
 * @swagger
 * /logout:
 *   get:
 *     summary: 用户登出
 *     description: 用户登出接口，清除token
 *     tags: [用户认证]
 *     security:
 *       - Authorization: []
 *     responses:
 *       200:
 *         description: 登出成功
 *       401:
 *         description: token无效或已过期
 *       500:
 *         description: 服务器错误
 */
router.get("/logout", async (ctx, next) => {
  try {
    // 从header中获取token
    const token = ctx.headers.authorization;
    if (!token) {
      ctx.status = 401;
      ctx.body = {
        code: 401,
        message: "未提供token",
      };
      return;
    }

    // 验证token
    const tokenInfo = await TokenManager.verifyToken(token);
    if (!tokenInfo) {
      ctx.status = 401;
      ctx.body = {
        code: 401,
        message: "token无效或已过期",
      };
      return;
    }

    // 清除token
    const removed = await TokenManager.removeToken(token);
    if (!removed) {
      throw new Error("清除token失败");
    }

    ctx.body = {
      code: 200,
      message: "登出成功",
    };
  } catch (error) {
    console.error("登出错误:", error);
    ctx.status = 500;
    ctx.body = {
      code: 500,
      message: "服务器内部错误",
    };
  }
});

/**
 * @swagger
 * /register:
 *   post:
 *     summary: 用户注册
 *     description: 新用户注册接口
 *     tags: [用户认证]
 *     requestBody:
 *       required: true
 *       content:
 *         application/json:
 *           schema:
 *             type: object
 *             required:
 *               - username
 *               - password
 *             properties:
 *               username:
 *                 type: string
 *                 description: 用户名
 *               password:
 *                 type: string
 *                 description: 密码
 *     responses:
 *       200:
 *         description: 注册成功
 *         content:
 *           application/json:
 *             schema:
 *               type: object
 *               properties:
 *                 code:
 *                   type: number
 *                   example: 200
 *                 message:
 *                   type: string
 *                   example: 注册成功
 *       400:
 *         description: 参数错误或用户名已存在
 *       500:
 *         description: 服务器错误
 */
router.post("/register", async (ctx, next) => {
  try {
    const { username, password } = ctx.request.body;

    // 参数验证
    if (!username || !password) {
      ctx.status = 400;
      ctx.body = {
        code: 400,
        message: "用户名和密码不能为空",
      };
      return;
    }

    // 检查用户名是否已存在
    const checkSql = "SELECT id FROM userinfo WHERE username = ?";
    const existingUsers = await query(checkSql, [username]);
    if (existingUsers.length > 0) {
      ctx.status = 400;
      ctx.body = {
        code: 400,
        message: "用户名已存在",
      };
      return;
    }

    // 插入新用户
    const insertSql = "INSERT INTO userinfo (username, password) VALUES (?, ?)";
    await query(insertSql, [username, password]);

    ctx.body = {
      code: 200,
      message: "注册成功",
    };
  } catch (error) {
    console.error("注册错误:", error);
    ctx.status = 500;
    ctx.body = {
      code: 500,
      message: "服务器内部错误",
    };
  }
});

/**
 * @swagger
 * /changePassword:
 *   post:
 *     summary: 修改密码
 *     description: 修改用户密码接口
 *     tags: [用户认证]
 *     security:
 *       - Authorization: []
 *     requestBody:
 *       required: true
 *       content:
 *         application/json:
 *           schema:
 *             type: object
 *             required:
 *               - oldPassword
 *               - newPassword
 *             properties:
 *               oldPassword:
 *                 type: string
 *                 description: 旧密码
 *               newPassword:
 *                 type: string
 *                 description: 新密码
 *     responses:
 *       200:
 *         description: 密码修改成功
 *         content:
 *           application/json:
 *             schema:
 *               type: object
 *               properties:
 *                 code:
 *                   type: number
 *                   example: 200
 *                 message:
 *                   type: string
 *                   example: 密码修改成功
 *       400:
 *         description: 参数错误
 *       401:
 *         description: 旧密码错误或未授权
 *       500:
 *         description: 服务器错误
 */
router.post("/changePassword", async (ctx, next) => {
  try {
    // 从header中获取token
    const token = ctx.headers.authorization;
    if (!token) {
      ctx.status = 401;
      ctx.body = {
        code: 401,
        message: "未提供token",
      };
      return;
    }

    // 验证token
    const tokenInfo = await TokenManager.verifyToken(token);
    if (!tokenInfo) {
      ctx.status = 401;
      ctx.body = {
        code: 401,
        message: "token无效或已过期",
      };
      return;
    }

    const { oldPassword, newPassword } = ctx.request.body;

    // 参数验证
    if (!oldPassword || !newPassword) {
      ctx.status = 400;
      ctx.body = {
        code: 400,
        message: "旧密码和新密码不能为空",
      };
      return;
    }

    // 验证旧密码
    const checkSql = "SELECT id FROM userinfo WHERE id = ? AND password = ?";
    const users = await query(checkSql, [tokenInfo.user_id, oldPassword]);
    if (users.length === 0) {
      ctx.status = 401;
      ctx.body = {
        code: 401,
        message: "旧密码错误",
      };
      return;
    }

    // 更新密码
    const updateSql = "UPDATE userinfo SET password = ? WHERE id = ?";
    await query(updateSql, [newPassword, tokenInfo.user_id]);

    // 清除所有token，强制重新登录
    await TokenManager.removeUserTokens(tokenInfo.user_id);

    ctx.body = {
      code: 200,
      message: "密码修改成功，请重新登录",
    };
  } catch (error) {
    console.error("修改密码错误:", error);
    ctx.status = 500;
    ctx.body = {
      code: 500,
      message: "服务器内部错误",
    };
  }
});

module.exports = router;
